/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package slicktest.factories.marshallers;

import java.io.File;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.newdawn.slick.SlickException;

import slicktest.entities.ImmobileEntity.ImmobileEntity;
import slicktest.entities.ImmobileEntity.Tower;

import slicktest.factories.Readers.SimpleTagReader;
import slicktest.factories.Readers.TagReader;
import slicktest.factories.marshallers.FileFilters.FileExtensionFilter;

import slicktest.types.DamageType;
import slicktest.types.TagStatusType;

import slicktest.util.TagUtil;

/**
 * turns .tow files into towers.
 * @author enrightt
 */
public class TowerMarshaller implements ImmobileEntityMarshaller {

    private File directory;
    private Map<String, Tower> towers;
    private TagReader reader;
    private final List<String> reqTags;
    private final List<String> optTags;

    public TowerMarshaller(String path) {
        directory = new File(path);
        towers = new HashMap<String, Tower>();
        reader = new SimpleTagReader();

        reqTags = new ArrayList<String>();
        reqTags.add("TYPE");
        reqTags.add("MAX_UPGRADES");
        reqTags.add("PASSABLE");
        reqTags.add("IMAGE");
        reqTags.add("ROF");
        reqTags.add("DAMAGE");
        reqTags.add("DAMAGE_TYPES");
        reqTags.add("SPEED");
        reqTags.add("SPLASH");
        reqTags.add("COST");
        reqTags.add("BUILD");

        optTags = new ArrayList<String>();
        optTags.add("RESTRICTIONS");
        optTags.add("SPAN");

        reader.setRequiredTags(reqTags);
        reader.setOptionalTags(optTags);

        if (directory.isDirectory()) {
            System.out.println("Directory exists, reading in all towers");
            readTowers();
        }
    }

    private void readTowers() {
        File[] fileList = directory.listFiles(new FileExtensionFilter(".tow"));

        for (int i = 0; i < fileList.length; i++) {
            File file = fileList[i];

            if (file.isFile()) {
                reader.setTargetFile(file);

                if (reader.getStatus() == TagStatusType.OK) {
                    System.out.println(fileList[i] + " is a well-formed tower file, making a new tower");
                    Map<String, String[]> reqTokens = reader.getRequiredTokens();
                    Map<String, String[]> optTokens = reader.getOptionalTokens();

                    createTower(reqTokens, optTokens);
                } else {
                    System.out.println(fileList[i] + " had errors");
                }
            }
        }
    }

    private void createTower(Map<String, String[]> reqTokens, Map<String, String[]> optTokens) {
        System.out.println("req: " + reqTokens);
        System.out.println("opt: " + optTokens);       

        //use a _ as a space in a name, then take it out again and replace it with an actual space
        String type = TagUtil.marshallString(reqTokens.get(reqTags.get(0))).replace('_', ' ');
        int maxUpgrades = TagUtil.marshallInt(reqTokens.get(reqTags.get(1)));
        boolean passable = TagUtil.marshallBoolean(reqTokens.get(reqTags.get(2)));
        String path = TagUtil.marshallString(reqTokens.get(reqTags.get(3)));
        
        double ROF = TagUtil.marshallDouble(reqTokens.get(reqTags.get(4)));
        double damage = TagUtil.marshallDouble(reqTokens.get(reqTags.get(5)));
        List<DamageType> damageTypes = TagUtil.marshallDamageTypes(reqTokens.get(reqTags.get(6)));
        double speed = TagUtil.marshallDouble(reqTokens.get(reqTags.get(7)));
        double splash = TagUtil.marshallDouble(reqTokens.get(reqTags.get(8)));
        double cost = TagUtil.marshallDouble(reqTokens.get(reqTags.get(9)));
        double build = TagUtil.marshallDouble(reqTokens.get(reqTags.get(10)));



        List<String> restrictions = TagUtil.marshallList(optTokens.get(optTags.get(0)));
        boolean[][] footprint = TagUtil.marshallFootprint(optTokens.get(optTags.get(1)));

        try {
            Tower t = new Tower(ROF, damage, speed, splash, cost, build, damageTypes, type, maxUpgrades, passable, restrictions, footprint, path);
            towers.put(type, t);
            System.out.println("added: " + t + " to the list of towers");
        } catch(SlickException ex) {
            System.out.println("invalid image path: " + path);
        }
    }

    public ImmobileEntity marshall(String type) throws SlickException {
        Tower result = null;
        if(towers.containsKey(type)) {
            result = new Tower(towers.get(type));
        } else {
            throw new SlickException(type + " was not found in the list of known towers.");
        }

        return result;
    }

    public List<ImmobileEntity> getModels() {
        List<ImmobileEntity> result = new LinkedList<ImmobileEntity>();
        Set<String> keySet = towers.keySet();

        Iterator<String> it = keySet.iterator();

        while(it.hasNext()) {
            String nextKey = it.next();
            ImmobileEntity nextEntity = towers.get(nextKey);
            result.add(nextEntity);
        }

        return result;
    }
}
